package com.sntk.organauthomanager.query;

import com.sntk.organauthomanager.application.dto.*;
import com.sntk.organauthomanager.application.mapper.RoleMapper;
import com.sntk.organauthomanager.application.mapper.UserRoleMapper;
import com.sntk.organauthomanager.infrastructure.db.entity.RoleEntity;
import com.sntk.organauthomanager.infrastructure.db.entity.UserRoleEntity;
import com.sntk.organauthomanager.infrastructure.db.repository.RoleDBRepository;
import com.sntk.organauthomanager.infrastructure.db.repository.UserRoleDBRepository;
import com.sntk.organauthomanager.query.param.RoleCondition;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Sort;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StringUtils;

import javax.persistence.criteria.CriteriaBuilder;
import javax.persistence.criteria.CriteriaQuery;
import javax.persistence.criteria.Predicate;
import javax.persistence.criteria.Root;
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;

/**
 * @ClassName: RoleQuery
 * @author: wgchao
 * @createTime: 2020/7/21 3:59 PM
 * @Description: TODO
 */
@Service
@Transactional(readOnly = true)
public class RoleQuery {
    @Autowired
    private RoleDBRepository roleDBRepository;
    @Autowired
    private UserRoleDBRepository userRoleDBRepository;
    @Autowired
    private RoleMapper roleMapper;
    @Autowired
    private UserRoleMapper userRoleMapper;

    public RoleDTO searchRole(String institutionNumber, String roleCode){
        RoleEntity roleEntity = roleDBRepository.findFirstByInstitutionNumberAndRoleCodeAndDelFalse(institutionNumber, roleCode);
        if(roleEntity == null){
            return null;
        }
        return roleMapper.transformToDTO(roleEntity);
    }

    public PageData<RoleVO> searchRolesOfCondition(RoleCondition roleCondition, OperatorInfo operatorInfo){
        Specification<RoleEntity> specification = new Specification<RoleEntity>() {
            @Override
            public Predicate toPredicate(Root<RoleEntity> root, CriteriaQuery<?> query, CriteriaBuilder criteriaBuilder) {
                List<Predicate> predicateList = new ArrayList<>();
                if(!StringUtils.isEmpty(roleCondition.getName())){
                    Predicate predicate = criteriaBuilder.equal(root.get("roleCode"), roleCondition.getName());
                    Predicate predicate1 = criteriaBuilder.like(root.get("roleName"), roleCondition.getName()+"%");
                    predicateList.add(criteriaBuilder.or(predicate, predicate1));
                }
                if(!StringUtils.isEmpty(roleCondition.getInstitutionNumber())){
                    Predicate predicate = criteriaBuilder.equal(root.get("institutionNumber"), roleCondition.getInstitutionNumber());
                    predicateList.add(predicate);
                }else{
                    Predicate predicate = criteriaBuilder.equal(root.get("institutionNumber"), operatorInfo.getInstitutionNumber());
                    predicateList.add(predicate);
                }
                Predicate predicate = criteriaBuilder.isFalse(root.get("del"));
                predicateList.add(predicate);

                Predicate[] predicates = new Predicate[predicateList.size()];
                return criteriaBuilder.and(predicateList.toArray(predicates));
            }
        };

        Pageable pageable = PageRequest.of(roleCondition.getCurrPageNo()-1, roleCondition.getLimit(), Sort.by(Sort.Order.desc("lastUpdateTime")));
        Page<RoleEntity> rolePage = roleDBRepository.findAll(specification, pageable);

        if(rolePage.isEmpty()){
            return new PageData<>(0L, roleCondition.getCurrPageNo(), null);
        }
        List<RoleVO> roleVOS = rolePage.stream().map(roleEntity -> {
            return roleMapper.transformToVO(roleEntity);
        }).collect(Collectors.toList());
        return new PageData<>(rolePage.getTotalElements(), roleCondition.getCurrPageNo(), roleVOS);
    }

    //通过角色,查询所有的用户列表,要分页

    public PageData<UserRoleDTO> searchUsersByRole(RoleCondition roleCondition, OperatorInfo operatorInfo){
        Specification<UserRoleEntity> specification = (Specification<UserRoleEntity>) (root, query, criteriaBuilder) -> {
            List<Predicate> predicateList = new ArrayList<>();
            if(!StringUtils.isEmpty(roleCondition.getInstitutionNumber())){
                Predicate predicate = criteriaBuilder.equal(root.get("institutionNumber"), roleCondition.getInstitutionNumber());
                predicateList.add(predicate);
            }
            if(!StringUtils.isEmpty(roleCondition.getName())){
                Predicate predicate = criteriaBuilder.equal(root.get("roleCode"), roleCondition.getName());
                predicateList.add(predicate);
            }

            Predicate[] predicates = new Predicate[predicateList.size()];
            return criteriaBuilder.and(predicateList.toArray(predicates));
        };

        Pageable pageable = PageRequest.of(roleCondition.getCurrPageNo()-1, roleCondition.getLimit(), Sort.by(Sort.Order.desc("uname")));
        Page<UserRoleEntity> userRoleEntities = userRoleDBRepository.findAll(specification,pageable);


        if(userRoleEntities.isEmpty()){
            return new PageData<>(0L, roleCondition.getCurrPageNo(), null);
        }
        List<UserRoleDTO> userRoleDTOS = userRoleEntities.stream().map(entry -> userRoleMapper.transformToDTO(entry)).collect(Collectors.toList());

        return new PageData<>(userRoleEntities.getTotalElements(), roleCondition.getCurrPageNo(), userRoleDTOS);
    }

    //根据人员查询角色
    public List<RoleVO> searchUserRoleByUname(String uname,OperatorInfo operatorInfo){

        List<UserRoleEntity> userRoleEntityList = userRoleDBRepository.findAllByUname(uname);
        if(userRoleEntityList == null || userRoleEntityList.isEmpty()){
            return null;
        }

        List<RoleVO> roleVOList = new ArrayList<>();
        for(UserRoleEntity item : userRoleEntityList){
            RoleEntity roleEntity = roleDBRepository.findFirstByInstitutionNumberAndRoleCodeAndDelFalse(item.getInstitutionNumber(),item.getRoleCode());
            if(roleEntity != null ){
                RoleVO roleVO = roleMapper.transformToVO(roleEntity);
                roleVOList.add(roleVO);
            }
        }

        return roleVOList;
    }

    //通过机构编号查询机构下的角色信息
    public List<RoleVO> searchRolesByinstitutionNumber(String institutionNumber,OperatorInfo operatorInfo){
        if(StringUtils.isEmpty(institutionNumber)){
            institutionNumber = operatorInfo.getInstitutionNumber();
        }
        List<RoleEntity> roleEntityList = roleDBRepository.findAllByInstitutionNumberAndDelFalse(institutionNumber);
        if(roleEntityList == null){
            return null;
        }

        List<RoleVO> roleVOList = roleEntityList.stream().map(entry -> roleMapper.transformToVO(entry)).collect(Collectors.toList());
        return roleVOList;
    }


}
